#include <iostream>
#include <string>
#include <atomic>
#include "Kernel.h"
#include "KernelExport.h"


using namespace std;
atomic_flag glbFlg = ATOMIC_FLAG_INIT;


template< typename T >
void * ShredPtr2VoidPtr(shared_ptr< T > &ptrShared)
{
	return reinterpret_cast<void *>(&ptrShared);
}

template< typename T >
shared_ptr< T > VoidPtr2ShredPtr(void * ptrVoid)
{
	return *reinterpret_cast<shared_ptr< T > *>(ptrVoid);
}

CKernel &GetKernel()
{	
	return *reinterpret_cast<CKernel *>(CKernel::Instance());
}

__declspec(dllexport) IKernel & __cdecl Kernel()
{
	return *dynamic_cast<IKernel *>( &GetKernel() );
}

__declspec(dllexport) IFrameTools & __cdecl FrameTools()
{
	return *reinterpret_cast<IFrameTools *>(GetKernel().Tools());
}

__declspec(dllexport) bool __cdecl KernelInit(PST_StartServerSidePara ptrStartServerSidePara)
{
	bool bRetVal = false;
	try
	{
		bRetVal = Kernel().Init(nullptr, nullptr, 0); 
		if (bRetVal)
		{ 
			if (!glbFlg.test_and_set())
			{
				glbPtrKernel = &Kernel();
			}	
			if (ptrStartServerSidePara != nullptr)
			{
				FrameTools().IPC().SetCallFunc(ptrStartServerSidePara->ptrCallBakFun, ptrStartServerSidePara->ptrCallBakFunAgu);
			}
		}

	}
	catch (...)
	{
		goto __end;
	}
__end:
	return bRetVal;
}

__declspec(dllexport) void __cdecl Stop()
{
	bool bRetVal = false;
	try
	{        		
		Kernel().DisableDataConnect();
	}
	catch (...)
	{
		goto __end;
	}
__end:
	return;
}

__declspec(dllexport) bool __cdecl InitServerSide(const char * pszConnectKcbpTxt, const char * pszConFileName)
{   
	char szOpenHandleName[CHAR_LEN_64] = { 0 };
	char szCloseHandleName[CHAR_LEN_64] = { 0 };
	glbPtrKernel = &Kernel();
	bool bRetVal = Kernel().Init(reinterpret_cast<void *>((char *)pszConFileName), nullptr, 0);	
	FrameTools().StrFun().ParaVal(szOpenHandleName, sizeof(szOpenHandleName), pszConnectKcbpTxt, "OpenHandle");
	FrameTools().StrFun().ParaVal(szCloseHandleName, sizeof(szCloseHandleName), pszConnectKcbpTxt, "CloseHandle");		
	if (bRetVal)
	{		
		bRetVal = FrameTools().IPC().InitThreadPool(1);
	}
	else if (!FrameTools().StrFun().IsEmpty(szCloseHandleName))
	{
		CreateMutexA(nullptr, false, szCloseHandleName);
	}
	if (!FrameTools().StrFun().IsEmpty(szOpenHandleName))
	{
		shared_ptr<ITrigger> ptrTrigger(FrameTools().CreateSmper(szOpenHandleName));
		ptrTrigger->Trigger(1);
	}
	if (!bRetVal)
	{
		::Sleep(2000);
	}
__end:
	return bRetVal;
}

__declspec(dllexport) bool AddAsynTaskByStr(const char * pszTask, const char * pszConnectId)
{
	return FrameTools().Client().SendASynReqTask(pszConnectId, pszTask);
}

__declspec(dllexport) bool AddAsynTaskByObj(IPacket * ptrTask, const char * pszConnectId)
{
	return (&FrameTools().Client() == nullptr) ? false : FrameTools().Client().SendASynReqTask(pszConnectId, ptrTask);
}

__declspec(dllexport) void __cdecl WriteLog(const char * pszLogTxt, const int iWriteLevel, const char * pszVersion)
{
	bool bRetVal = false;	
	if (!Kernel().InitFlg())
	{
		goto __end;
	}
	if (Kernel().StopFlg())
	{
		goto __end;
	}
	if (&FrameTools().Client() == nullptr)
	{
		goto __end;
	}
	Kernel().WriteLog(pszLogTxt, iWriteLevel, pszVersion);
__end:
	return;
}

__declspec(dllexport) bool __cdecl StartServerSide(PST_StartServerSidePara ptrStartServerSidePara)
{
	bool bRetVal = false;	

	if (!Kernel().InitFlg())
	{
		bRetVal = KernelInit(nullptr);
	}	
	bRetVal = &FrameTools().Client() == nullptr ? false : FrameTools().Client().InitClient(ptrStartServerSidePara);
__end:
	return bRetVal;
}

__declspec(dllexport) bool __cdecl AddSyncTaskByStr(const char * pszTask, char ** pszRetVal, int &refiSize, int iTimeOut, const char * pszConnectId)
{	
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().SendSyncReqTask(pszConnectId, pszTask, pszRetVal, refiSize, iTimeOut);
}

__declspec(dllexport) bool __cdecl AddSyncTaskByObj(IPacket * ptrTask, IPacket ** ptrRetVal, int iTimeOut, const char * pszConnectId)
{
	bool bRetVal = false;
    IData * ptrData = nullptr;
	if (&FrameTools().Client() == nullptr) goto __end;
    bRetVal = FrameTools().Client().SendSyncReqTask(pszConnectId, ptrTask, &ptrData, iTimeOut);
    (*ptrRetVal) = dynamic_cast<IPacket *>(ptrData);
__end:
	return bRetVal;
}

__declspec(dllexport) bool __cdecl KcbpRunAsynTaskByStr(const char * pszTask, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().KcbpRunAsynTask(pszTask, pszIpAdd);
}

__declspec(dllexport) bool __cdecl KcbpRunAsynTaskByObj(IPacket * ptrTask, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().KcbpRunAsynTask(ptrTask, pszIpAdd);
}

__declspec(dllexport) bool __cdecl KcbpRunSyncTaskByStr(const char * pszTask, char ** pszRetVal, int & refiSize, int iTimeOut, const char * pszIpAdd)
{
	return  &FrameTools().Client() == nullptr ? false : FrameTools().Client().KcbpRunSyncTask(pszTask, pszRetVal, refiSize, iTimeOut, pszIpAdd);
}

__declspec(dllexport) bool __cdecl KcbpRunSyncTaskByObj(IPacket * ptrTask, IPacket ** ptrRetVal, int iTimeOut, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().KcbpRunSyncTask(ptrTask, ptrRetVal, iTimeOut, pszIpAdd);
}

__declspec(dllexport) bool __cdecl MaRunAsynTaskByStr(const char * pszTask, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunAsynTask(pszTask, pszIpAdd);
}

__declspec(dllexport) bool __cdecl MaRunAsynTaskByObj(IPacket * ptrTask, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunAsynTask(ptrTask, pszIpAdd);
}

__declspec(dllexport) bool __cdecl MaRunSyncTaskByStr(const char * pszTask, char ** pszRetVal, unsigned long & refiSize, int iTimeOut, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunSyncTask(pszTask, pszRetVal, refiSize, iTimeOut, pszIpAdd);
}

__declspec(dllexport) bool __cdecl MaRunSyncTaskByObj(IPacket * ptrTask, IPacket ** ptrRetVal, int iTimeOut, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunSyncTask(ptrTask, ptrRetVal, iTimeOut, pszIpAdd);
}

__declspec(dllexport) bool __cdecl MaRunSubTaskByStr(const char * pszTask, char ** pszRetVal, unsigned long & refiSize, int iTimeOut, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunSubTask(pszTask, pszRetVal, refiSize, iTimeOut, pszIpAdd);;
}

__declspec(dllexport) bool __cdecl MaRunSubTaskByObj(IPacket * ptrTask, IPacket ** ptrRetVal, int iTimeOut, const char * pszIpAdd)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunSubTask(ptrTask, ptrRetVal, iTimeOut, pszIpAdd);
}

__declspec(dllexport) bool __cdecl UnSubSynByStr(const char * pszTask, char ** pszRetVal, unsigned long & refiSize, int iTimeOut)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunUnSubTask(pszTask, pszRetVal, refiSize, iTimeOut);;
}

__declspec(dllexport) bool __cdecl UnSubSynByObj(IPacket * ptrTask, IPacket ** ptrRetVal, int iTimeOut)
{
	return &FrameTools().Client() == nullptr ? false : FrameTools().Client().MaRunUnSubTask(ptrTask, ptrRetVal, iTimeOut);
}

__declspec(dllexport) bool __cdecl InitKcbpConnectInfo(PST_KCBP_CONNECT_INFO ptrKcbpConnectInfo)
{
    return &FrameTools().Client() == nullptr ? false : FrameTools().Client().InitKcbpConnectInfo(ptrKcbpConnectInfo);
}

__declspec(dllexport) void __cdecl ClearDataBuffer(char ** pszDataBuffer)
{
    if ((*pszDataBuffer) == nullptr)
    {
        return;
    }
    char * ptrDataBuf = (*pszDataBuffer);
    delete ptrDataBuf;
    ptrDataBuf = nullptr;
    (*pszDataBuffer) = nullptr;
}

void * __cdecl InitJson()
{
  	return reinterpret_cast<void *>(Instance<IPacket>("CPacketJson", nullptr, nullptr, 0));
}

void __cdecl FreeJson(void ** ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(*ptrPktJson);
	delete ptrJson;
	ptrJson = nullptr;
	(*ptrPktJson) = nullptr;
	return;
}

char * __cdecl Key(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return const_cast<char *>(ptrJson->Key());
}

void __cdecl SetKey(void * ptrPktJson, const char * pszKey)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	ptrJson->SetKey(pszKey);
	return;
}

char * __cdecl MSG_FLG(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return const_cast<char *>(ptrJson->MSG_FLG());
}

void __cdecl SetMsgFlg(void * ptrPktJson, const char * pszMsgFlg)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	ptrJson->SetMsgFlg(pszMsgFlg);
	return;
}

int __cdecl MSG_CODE(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);	
	return ptrJson->MSG_CODE();
}

char * __cdecl MSG_TEXT(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return const_cast<char *>(ptrJson->MSG_TEXT());
}

char * __cdecl LBM_NO(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return const_cast<char *>(ptrJson->LBM_NO());
}

int __cdecl TIME(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->TIME();
}

void __cdecl SetTime(void * ptrPktJson, int ulTime)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	ptrJson->SetTime(ulTime);
	return;
}

long long __cdecl SOURCE_PROCESS_ID(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->SOURCE_PROCESS_ID();
}

void __cdecl SetSourceProcessID(void * ptrPktJson, long long llProID)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->SetSourceProcessID(llProID);
}

long long __cdecl DESTINATION_PROCESS_ID(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->DESTINATION_PROCESS_ID();
}

void __cdecl SetDestinationProcessID(void * ptrPktJson, long long llProID)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->SetDestinationProcessID(llProID);
}

bool __cdecl UpdFirstSet(void * ptrPktJson, const int &iMsgCode, const char * pszMsgText, const char * LbmNo)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->UpdFirstSet(iMsgCode, pszMsgText, LbmNo);
}

bool __cdecl Parse(void * ptrPktJson, const char * pszJsonTxt)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->Parse(pszJsonTxt);
}

void * __cdecl Append(void * ptrPktJson)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->Append();
}

int __cdecl RECORD_COUNT(void * ptrPktJson, const char * pszTableName)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->RECORD_COUNT(pszTableName);
}

void * __cdecl ReadRecord(void * ptrPktJson, const char * pszTableName, int iRecNo)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->ReadRecord(pszTableName, iRecNo);
}

bool __cdecl Save(void * ptrPktJson, const char * pszTableName, void * ptrRecInfo)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->Save(pszTableName, ptrRecInfo);
}

void __cdecl Clear(void * ptrPktJson, const char * pszTableName)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->Clear(pszTableName);
}

bool __cdecl EmptyFlg(void * ptrPktJson, const char * pszTableName)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->EmptyFlg(pszTableName);
}

char * __cdecl GetFieldValueAsString(void * ptrPktJson, void * ptrRecInfo, const char * pszFieldName)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return const_cast<char *>(ptrJson->GetFieldValueAsString(ptrRecInfo, pszFieldName, ""));
}

bool __cdecl SetFieldValue(void * ptrPktJson, void * ptrRecInfo, const char * pszFieldName, const char *pszValue)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->SetFieldValue(ptrRecInfo, pszFieldName, pszValue);
}

char * __cdecl AsString(void * ptrPktJson, unsigned long &ulLength, const char * pszTableName /*= NULL*/)
{
	const char * pszRetVal = nullptr;
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	pszRetVal = ptrJson->AsString(reinterpret_cast<void *>(const_cast<char *>(pszTableName)));
	ulLength = strlen(pszRetVal);
	return const_cast<char *>(pszRetVal);
}

bool __cdecl TableExist(void * ptrPktJson, const char * pszTableName)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->TableExist(pszTableName);
}

bool __cdecl FieldExist(void * ptrPktJson, void * ptrRecInfo, const char * pszFieldName)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
	return ptrJson->FieldExist(ptrRecInfo, pszFieldName);
}

bool __cdecl FieldNameInfo(void * ptrPktJson, const char * pszTableName, char ** pszFieldNameList)
{
	IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);	
	return ptrJson->FieldNameInfo(pszTableName, pszFieldNameList);
}

bool __cdecl AddAsynTaskByProcessID(unsigned long ulProcessId, const char * ptrTask)
{
	bool bRetVal = false;
	if (ptrTask == nullptr)
	{
		goto __end;
	}
	if (ulProcessId == 0)
	{
		goto __end;
	}
	if (&FrameTools().IPC() == nullptr)
	{
		goto __end;
	}
	IPacket * ptrPktTask = Instance<IPacket>("CPacketJson", reinterpret_cast<void *>(const_cast<char *>(ptrTask)), nullptr, 0);
	FrameTools().IPC().SendAsynTask(ulProcessId, ptrPktTask);
__end:
	return bRetVal;
}

bool __cdecl AddAsynTaskByAppName(const char * pszAppName, const char * ptrTask)
{
	bool bRetVal = false;
	if (ptrTask == nullptr)
	{
		goto __end;
	}
	if (pszAppName == nullptr)
	{
		goto __end;
	}
	if (&FrameTools().IPC() == nullptr)
	{
		goto __end;
	}
    IPacket * ptrPktTask = Instance<IPacket>("CPacketJson", reinterpret_cast<void *>(const_cast<char *>(ptrTask)), nullptr, 0);
	FrameTools().IPC().SendAsynTask(pszAppName, ptrPktTask);
__end:
	return bRetVal;
}

bool __cdecl TOP_FLAG(void * ptrPktJson)
{
    IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
    return ptrJson->TOP_FLAG();
}

void __cdecl SetTopFlag(void * ptrPktJson, bool bTopFlg)
{
    IPacket * ptrJson = reinterpret_cast<IPacket *>(ptrPktJson);
    ptrJson->SetTopFlag(bTopFlg);
}